home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / WINDOWS / DIRECT3D.ZIP / TUNNEL.C < prev   
Encoding:
C/C++ Source or Header  |  1996-09-18  |  22.8 KB  |  713 lines

  1. #include <windows.h>
  2. #include <ddraw.h>
  3. #include <math.h>
  4. #include <malloc.h>
  5. #include "dxproto.h"
  6. #include "d3d.h"
  7. #include "appfuncs.h"
  8. #include "d3dmacs.h"
  9.  
  10. LPD3DVECTOR 
  11. D3DVECTORNormalise(LPD3DVECTOR v)
  12. {
  13.     float vx, vy, vz, inv_mod;
  14.     vx = v->x;
  15.     vy = v->y;
  16.     vz = v->z;
  17.     if ((vx == 0) && (vy == 0) && (vz == 0))
  18.         return v;
  19.     inv_mod = (float)(1.0 / sqrt(vx * vx + vy * vy + vz * vz));
  20.     v->x = vx * inv_mod;
  21.     v->y = vy * inv_mod;
  22.     v->z = vz * inv_mod;
  23.     return v;
  24. }
  25.  
  26. LPD3DVECTOR 
  27. D3DVECTORCrossProduct(LPD3DVECTOR lpd, LPD3DVECTOR lpa, LPD3DVECTOR lpb)
  28. {
  29.  
  30.     lpd->x = lpa->y * lpb->z - lpa->z * lpb->y;
  31.     lpd->y = lpa->z * lpb->x - lpa->x * lpb->z;
  32.     lpd->z = lpa->x * lpb->y - lpa->y * lpb->x;
  33.     return lpd;
  34. }
  35.  
  36. LPD3DMATRIX 
  37. D3DMATRIXInvert(LPD3DMATRIX d, LPD3DMATRIX a)
  38. {
  39.     d->_11 = a->_11;
  40.     d->_12 = a->_21;
  41.     d->_13 = a->_31;
  42.     d->_14 = a->_14;
  43.  
  44.     d->_21 = a->_12;
  45.     d->_22 = a->_22;
  46.     d->_23 = a->_32;
  47.     d->_24 = a->_24;
  48.  
  49.     d->_31 = a->_13;
  50.     d->_32 = a->_23;
  51.     d->_33 = a->_33;
  52.     d->_34 = a->_34;
  53.  
  54.     d->_41 = a->_14;
  55.     d->_42 = a->_24;
  56.     d->_43 = a->_34;
  57.     d->_44 = a->_44;
  58.  
  59.     return d;
  60. }
  61.  
  62. LPD3DMATRIX 
  63. D3DMATRIXSetRotation(LPD3DMATRIX lpM, LPD3DVECTOR lpD, LPD3DVECTOR lpU)
  64. {
  65.     float t;
  66.     D3DVECTOR d, u, r;
  67.  
  68.     /*
  69.      * Normalise the direction vector.
  70.      */
  71.     d.x = lpD->x;
  72.     d.y = lpD->y;
  73.     d.z = lpD->z;
  74.     D3DVECTORNormalise(&d);
  75.  
  76.     u.x = lpU->x;
  77.     u.y = lpU->y;
  78.     u.z = lpU->z;
  79.     /*
  80.      * Project u into the plane defined by d and normalise.
  81.      */
  82.     t = u.x * d.x + u.y * d.y + u.z * d.z;
  83.     u.x -= d.x * t;
  84.     u.y -= d.y * t;
  85.     u.z -= d.z * t;
  86.     D3DVECTORNormalise(&u);
  87.  
  88.     /*
  89.      * Calculate the vector pointing along the matrix x axis (in a right
  90.      * handed coordinate system) using cross product.
  91.      */
  92.     D3DVECTORCrossProduct(&r, &u, &d);
  93.  
  94.     lpM->_11 = r.x;
  95.     lpM->_12 = r.y, lpM->_13 = r.z;
  96.     lpM->_21 = u.x;
  97.     lpM->_22 = u.y, lpM->_23 = u.z;
  98.     lpM->_31 = d.x;
  99.     lpM->_32 = d.y;
  100.     lpM->_33 = d.z;
  101.  
  102.     return lpM;
  103. }
  104.  
  105. void 
  106. spline(LPD3DVECTOR p, float t, LPD3DVECTOR p1, LPD3DVECTOR p2,
  107.        LPD3DVECTOR p3, LPD3DVECTOR p4)
  108. {
  109.     double t2, t3;
  110.     float m1, m2, m3, m4;
  111.  
  112.     t2 = (double)(t * t);
  113.     t3 = t2 * (double)t;
  114.  
  115.     m1 = (float)((-1.0 * t3) + (2.0 * t2) + (-1.0 * (double)t));
  116.     m2 = (float)((3.0 * t3) + (-5.0 * t2) + (0.0 * (double)t) + 2.0);
  117.     m3 = (float)((-3.0 * t3) + (4.0 * t2) + (1.0 * (double)t));
  118.     m4 = (float)((1.0 * t3) + (-1.0 * t2) + (0.0 * (double)t));
  119.  
  120.     m1 /= (float)2.0;
  121.     m2 /= (float)2.0;
  122.     m3 /= (float)2.0;
  123.     m4 /= (float)2.0;
  124.  
  125.     p->x = p1->x * m1 + p2->x * m2 + p3->x * m3 + p4->x * m4;
  126.     p->y = p1->y * m1 + p2->y * m2 + p3->y * m3 + p4->y * m4;
  127.     p->z = p1->z * m1 + p2->z * m2 + p3->z * m3 + p4->z * m4;
  128. }
  129.  
  130. static D3DEXECUTEDATA d3dExData;
  131. static LPDIRECT3DEXECUTEBUFFER lpD3DExBuf;
  132. static D3DEXECUTEBUFFERDESC debDesc;
  133.  
  134. LPDIRECT3DMATERIAL lpbmat;
  135. LPDIRECT3DMATERIAL lpmat;   /* Material object */
  136.  
  137. D3DMATRIXHANDLE hProj;
  138. D3DMATRIX proj = {
  139.     D3DVAL(2.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
  140.     D3DVAL(0.0), D3DVAL(2.0), D3DVAL(0.0), D3DVAL(0.0),
  141.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(1.0),
  142.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(-1.0), D3DVAL(0.0)
  143. };
  144. D3DMATRIXHANDLE hView;
  145. D3DMATRIX view = {
  146.     D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
  147.     D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0),
  148.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0),
  149.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(10.0), D3DVAL(1.0)
  150. };
  151. D3DMATRIXHANDLE hWorld;
  152. D3DMATRIX world = {
  153.     D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
  154.     D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0),
  155.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0),
  156.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0)
  157. };
  158. D3DMATRIX identity = {
  159.     D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
  160.     D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0),
  161.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0),
  162.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0)
  163. };
  164.  
  165. #define PI 3.14159265359
  166.  
  167. #define SEGMENTS 40
  168. #define SIDES 8       /* Number of sides on each ring. */
  169. #define TEX_RINGS 5   /* Number of rings to stretch the texture over. */
  170. #define NUM_V (SIDES*(SEGMENTS+1)) // Number of vertices in memory at once
  171. #define NUM_TRI (SIDES*SEGMENTS*2) // Number of triangles in memory
  172. #define TUBE_R 1.0       /* Radius of the tube. */
  173. #define SPLINE_POINTS 50
  174.  
  175. #define SEGMENT_LENGTH 0.07
  176. #define SPEED 0.02
  177. #define DEPTH 0.8
  178. #define PATH_LENGTH (SPLINE_POINTS - 1)
  179.  
  180. static struct {
  181.     LPD3DVERTEX lpV;        /* Points to the vertices. */
  182.     LPD3DTRIANGLE lpTri;    /* Points to the triangles which make up the
  183.                              * segments.
  184.                              */
  185.     int TriOffset;          /* Offset into the execute buffer were the
  186.                              * triangle list is found.
  187.                              */
  188.     LPD3DVECTOR lpPoints;   /* Points to the points defining the spline
  189.                              * curve.
  190.                              */
  191.     D3DMATERIALHANDLE hMat; /* Handle for the material on the tube. */
  192.     D3DTEXTUREHANDLE hTex;  /* Handle for the texture on the material.*/
  193.     D3DLIGHT light;             /* Structure defining the light. */
  194.     LPDIRECT3DLIGHT lpD3DLight; /* Object pointer for the light. */
  195.     D3DVECTOR cameraP, cameraD, cameraN; /* Vectors defining the camera 
  196.                                           * position, direction and up.
  197.                                           */
  198.     float cameraPos;                     /* Camera position along the 
  199.                                           * spline curve.
  200.                                           */
  201.     D3DVECTOR endP, endD, endN; /* Vectors defining the position, 
  202.                                  * direction and up at the foremost end of
  203.                                  * the section in memory.
  204.                                  */
  205.     float endPos; /* Position along the spline curve of the end. */
  206.     int currentRing, currentSegment; /* Numbers of the ring and tube at 
  207.                                       * the back end of the section.
  208.                                       */
  209. } tube;
  210.  
  211.  
  212. void 
  213. PositionCamera(LPD3DVECTOR lpP, LPD3DVECTOR lpD, LPD3DVECTOR lpN, 
  214.                LPD3DMATRIX lpM)
  215. {
  216.     D3DMATRIX tmp;
  217.  
  218.     tmp._14 = tmp._24 = tmp._34 = tmp._41 = tmp._42 = tmp._43 = (float)0.0;
  219.     tmp._44 = (float)1.0;
  220.     D3DMATRIXSetRotation(&tmp, lpD, lpN);
  221.     D3DMATRIXInvert(lpM, &tmp);
  222.  
  223.     lpM->_41=-(lpM->_11 * lpP->x + lpM->_21 * lpP->y + lpM->_31 * lpP->z);
  224.     lpM->_42=-(lpM->_12 * lpP->x + lpM->_22 * lpP->y + lpM->_32 * lpP->z);
  225.     lpM->_43=-(lpM->_13 * lpP->x + lpM->_23 * lpP->y + lpM->_33 * lpP->z);
  226. }
  227.  
  228. void 
  229. MoveToPosition(float position, LPD3DVECTOR lpP, LPD3DVECTOR lpD, 
  230.                LPD3DVECTOR lpN)
  231. {
  232.     LPD3DVECTOR lpSplinePoint[4];
  233.     D3DVECTOR pp, x;
  234.     int i, j;
  235.     float t;
  236.  
  237.     i = 0;
  238.     t = position;
  239.     while (t > 1.0)
  240.     {
  241.         i++;
  242.         if (i == SPLINE_POINTS)
  243.             i = 0;
  244.         t -= (float)1.0;
  245.     }
  246.     for (j = 0; j < 4; j++)
  247.     {
  248.         lpSplinePoint[j] = &tube.lpPoints[i];
  249.         i++;
  250.         if (i == SPLINE_POINTS)
  251.             i = 0;
  252.     }
  253.  
  254.     spline(lpP, t, lpSplinePoint[0], lpSplinePoint[1], lpSplinePoint[2],
  255.            lpSplinePoint[3]);
  256.     spline(&pp, t - (float)0.01, lpSplinePoint[0], lpSplinePoint[1],
  257.            lpSplinePoint[2], lpSplinePoint[3]);
  258.  
  259.     lpD->x = lpP->x - pp.x;
  260.     lpD->y = lpP->y - pp.y;
  261.     lpD->z = lpP->z - pp.z;
  262.     D3DVECTORNormalise(lpD);
  263.  
  264.     D3DVECTORNormalise(lpN);
  265.     D3DVECTORCrossProduct(&x, lpN, lpD);
  266.     D3DVECTORCrossProduct(lpN, &x, lpD);
  267.     lpN->x = -lpN->x;
  268.     lpN->y = -lpN->y;
  269.     lpN->z = -lpN->z;
  270.     D3DVECTORNormalise(lpN);
  271. }
  272.  
  273.  
  274. static void 
  275. MakeRing(LPD3DVECTOR p, LPD3DVECTOR d, LPD3DVECTOR n, float tv,
  276.          LPD3DVERTEX joint)
  277. {
  278.     int spoke;
  279.     float theta, u, v, x, y, z;
  280.     D3DVECTOR nxd;
  281.  
  282.     D3DVECTORCrossProduct(&nxd, n, d);
  283.     for (spoke = 0; spoke < SIDES; spoke++)
  284.     {
  285.         theta = (float)(2.0 * PI) * spoke / SIDES;
  286.         v = (float)sin(theta);
  287.         u = (float)cos(theta);
  288.         x = u * nxd.x + v * n->x;
  289.         y = u * nxd.y + v * n->y;
  290.         z = u * nxd.z + v * n->z;
  291.         joint[spoke].x = (float)TUBE_R * x + p->x;
  292.         joint[spoke].y = (float)TUBE_R * y + p->y;
  293.         joint[spoke].z = (float)TUBE_R * z + p->z;
  294.         joint[spoke].nx = -x;
  295.         joint[spoke].ny = -y;
  296.         joint[spoke].nz = -z;
  297.         joint[spoke].tu = (float)1.0 - theta / (float)(2.0 * PI);
  298.         joint[spoke].tv = tv;
  299.  
  300.     }
  301. }
  302.  
  303.  
  304. void 
  305. MakeSegment(int ring1, int ring2, LPD3DTRIANGLE lpTri)
  306. {
  307.     int side, triangle = 0;
  308.  
  309.     for (side = 0; side < SIDES; side++) {
  310.         /*
  311.          * Each side consists of two triangles.
  312.          */
  313.         lpTri[triangle].v1 = ring1 * SIDES + side;
  314.         lpTri[triangle].v2 = ring2 * SIDES + side;
  315.         lpTri[triangle].v3 = ring2 * SIDES + ((side + 1) % SIDES);
  316.         
  317.         /*
  318.          * for wireframe only need first two edges.
  319.          * Start a two triangle flat fan for each tunnel face.
  320.          */
  321.                 
  322.         lpTri[triangle].wFlags = D3DTRIFLAG_STARTFLAT(1);
  323.         lpTri[triangle].wFlags |= D3DTRIFLAG_EDGEENABLE1 |
  324.                                   D3DTRIFLAG_EDGEENABLE2;
  325.         
  326.         triangle++;
  327.         lpTri[triangle].v2 = ring2 * SIDES + ((side + 1) % SIDES);
  328.         lpTri[triangle].v3 = ring1 * SIDES + ((side + 1) % SIDES);
  329.         lpTri[triangle].v1 = ring1 * SIDES + side;
  330.         
  331.         /*
  332.          * Dont need any edges for wireframe.
  333.          */
  334.         lpTri[triangle].wFlags = D3DTRIFLAG_EVEN;
  335.         
  336.         triangle++;
  337.     }
  338. }
  339.  
  340.  
  341. /*
  342.  * Creates a new segment of the tunnel at the current end position.
  343.  * Creates a new ring and segment.
  344.  */
  345. void 
  346. UpdateTubeInMemory(void)
  347. {
  348.     static int texRing = 0; /* Static counter defining the position of
  349.                              * this ring on the texture.
  350.                              */
  351.     int endRing; /* The ring at the end of the tube in memory. */
  352.     int RingOffset, SegmentOffset; /* Offsets into the vertex and triangle 
  353.                                     * lists for the new data.
  354.                                     */
  355.     /*
  356.      * Replace the back ring with a new ring at the front of the tube
  357.      * in memory.
  358.      */
  359.     memcpy(&tube.lpV[SIDES], &tube.lpV[0], sizeof(tube.lpV[0]) * (NUM_V - SIDES));
  360.     MakeRing(&tube.endP, &tube.endD, &tube.endN, texRing/(float)TEX_RINGS,
  361.              &tube.lpV[0]);
  362.     /*
  363.      * Replace the back segment with a new segment at the front of the
  364.      * tube in memory. Update the current end position of the tube in
  365.      * memory.
  366.      */
  367.     endRing = (tube.currentRing + SEGMENTS) % (SEGMENTS + 1);
  368.     MoveToPosition(tube.endPos, &tube.endP, &tube.endD, &tube.endN);
  369.     /*
  370.      * Update the execute buffer with the new vertices and triangles.
  371.      */
  372.     RingOffset = sizeof(D3DVERTEX) * tube.currentRing * SIDES;
  373.     SegmentOffset = sizeof(D3DTRIANGLE) * tube.currentSegment * SIDES * 2;
  374.     memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
  375.     debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
  376.     if (lpD3DExBuf->lpVtbl->Lock(lpD3DExBuf, &debDesc) != D3D_OK)
  377.         return;
  378.     memcpy((char *) debDesc.lpData,
  379.            &tube.lpV[0], sizeof(D3DVERTEX) * NUM_V);
  380.     lpD3DExBuf->lpVtbl->Unlock(lpD3DExBuf);
  381.     /*
  382.      * Update the position of the back of the tube in memory and texture
  383.      * counter.
  384.      */
  385.     tube.currentRing = (tube.currentRing + 1) % (SEGMENTS + 1);
  386.     tube.currentSegment = (tube.currentSegment + 1) % SEGMENTS;
  387.     texRing = (texRing + 1) % TEX_RINGS;
  388. }
  389.  
  390.  
  391. /*
  392.  * Move the camera through the tunnel.  Create new segments of the tunnel
  393.  * when the camera gets close to the end of the section in memory.
  394.  */
  395. void 
  396. MoveCamera(LPDIRECT3DDEVICE lpDev, LPDIRECT3DVIEWPORT lpView)
  397. {
  398.     /*
  399.      * Update the position on curve and camera vectors.
  400.      */
  401.     tube.cameraPos += (float)SPEED;
  402.     if (tube.cameraPos > PATH_LENGTH)
  403.         tube.cameraPos -= PATH_LENGTH;
  404.     MoveToPosition(tube.cameraPos, &tube.cameraP, &tube.cameraD,
  405.                    &tube.cameraN);
  406.     /*
  407.      * If the camera is close to the end, add a new segment.
  408.      */
  409.     if (tube.endPos - tube.cameraPos < DEPTH) {
  410.         tube.endPos = tube.endPos + (float)SEGMENT_LENGTH;
  411.         if (tube.endPos > PATH_LENGTH)
  412.             tube.endPos -= PATH_LENGTH;
  413.         UpdateTubeInMemory();
  414.     }
  415. }
  416.  
  417.  
  418. /*
  419.  * Modify the buffer between rendering frames
  420.  */
  421. static void 
  422. TickScene(LPDIRECT3DDEVICE lpDev, LPDIRECT3DVIEWPORT lpView)
  423. {
  424.     MoveCamera(lpDev, lpView);
  425. }
  426.  
  427. D3DRECT RenderScene(LPDIRECT3DDEVICE lpDev, LPDIRECT3DVIEWPORT lpView)
  428. {
  429.     HRESULT ddrval;
  430.  
  431.     /*
  432.      * Move the camera by updating the view matrix and move the light.
  433.      */
  434.     PositionCamera(&tube.cameraP, &tube.cameraD, &tube.cameraN, &view);
  435.     ddrval = lpDev->lpVtbl->SetMatrix(lpDev, hView, &view);
  436.  
  437.     tube.light.dvPosition.x = tube.cameraP.x;
  438.     tube.light.dvPosition.y = tube.cameraP.y;
  439.     tube.light.dvPosition.z = tube.cameraP.z;
  440.     ddrval = tube.lpD3DLight->lpVtbl->SetLight(tube.lpD3DLight, &tube.light);
  441.  
  442.     ddrval = lpDev->lpVtbl->BeginScene(lpDev);
  443.     ddrval = lpDev->lpVtbl->Execute(lpDev, lpD3DExBuf, lpView, D3DEXECUTE_CLIPPED);
  444.     ddrval = lpDev->lpVtbl->EndScene(lpDev);
  445.     ddrval = lpD3DExBuf->lpVtbl->GetExecuteData(lpD3DExBuf, &d3dExData);
  446.     TickScene(lpDev, lpView);
  447.     return(d3dExData.dsStatus.drExtent);
  448. }
  449.  
  450. BOOL
  451. InitScene(DXDevice *Dev)
  452. {
  453.     float position;             /* Curve position counter. */
  454.     int i;                      /* counter */
  455.  
  456.      LoadPPMTexture(Dev, "tex1.ppm");
  457.     LoadPPMTexture(Dev, "tex2.ppm");
  458.     LoadPPMTexture(Dev, "tex3.ppm");
  459.    /*
  460.      * Reserved memory for vertices, triangles and spline points.
  461.      */
  462.     tube.lpV = (LPD3DVERTEX) malloc(sizeof(D3DVERTEX) * NUM_V);
  463.     tube.lpTri = (LPD3DTRIANGLE) malloc(sizeof(D3DTRIANGLE) * NUM_TRI);
  464.     tube.lpPoints = (LPD3DVECTOR) malloc(sizeof(D3DVECTOR)*SPLINE_POINTS);
  465.     /*
  466.      * Generate spline points
  467.      */
  468.     for (i = 0; i < SPLINE_POINTS; i++) {
  469. #if 1
  470.         tube.lpPoints[i].x = (float)(cos(i * 4.0) * 20.0);
  471.         tube.lpPoints[i].y = (float)(sin(i * 4.0) * 20.0);
  472.         tube.lpPoints[i].z = i * (float)20.0;
  473. #else
  474.         tube.lpPoints[i].x = (float)0.0;
  475.         tube.lpPoints[i].y = (float)0.0;
  476.         tube.lpPoints[i].z = i * (float)20.0;
  477. #endif
  478.     }
  479.     /*
  480.      * Create the initial tube section in memory.
  481.      */
  482.     tube.endN.x = (float)0.0;
  483.     tube.endN.y = (float)1.0;
  484.     tube.endN.z = (float)0.0;
  485.     position = (float)0.0;
  486.     for (i = 0; i < SEGMENTS + 1; i++) {
  487.         MoveToPosition(position, &tube.endP, &tube.endD, &tube.endN);
  488.         position += (float)SEGMENT_LENGTH;
  489.         MakeRing(&tube.endP, &tube.endD, &tube.endN, 
  490.                  (float)(i % TEX_RINGS) / TEX_RINGS,
  491.                  &tube.lpV[(SEGMENTS - i) * SIDES]);
  492.     }
  493.     for (i = 0; i < SEGMENTS; i++)
  494.         MakeSegment(i + 1, i, &tube.lpTri[i * SIDES * 2]);
  495.     /*
  496.      * Move the camera to the begining and set some globals
  497.      */
  498.     tube.cameraN.x = (float)0.0;
  499.     tube.cameraN.y = (float)1.0;
  500.     tube.cameraN.z = (float)0.0;
  501.     MoveToPosition((float)0.0, &tube.cameraP, &tube.cameraD, &tube.cameraN);
  502.     tube.currentRing = 0;
  503.     tube.currentSegment = 0;
  504.     tube.cameraPos = (float)0.0;
  505.     tube.endPos = position;
  506.     return TRUE;
  507. }
  508.  
  509. void
  510. ReleaseScene(DXDevice *Dev)
  511. {
  512.     ReleaseAllTextures(Dev);
  513.     if (tube.lpPoints)
  514.         free(tube.lpPoints);
  515.     if (tube.lpTri)
  516.         free(tube.lpTri);
  517.     if (tube.lpV)
  518.         free(tube.lpV);
  519. }
  520.  
  521. void
  522. ReleaseView(LPDIRECT3DVIEWPORT lpView)
  523. {
  524.     if (lpView)
  525.         lpView->lpVtbl->DeleteLight(lpView, tube.lpD3DLight);
  526.     RELEASE(lpD3DExBuf);
  527.     RELEASE(tube.lpD3DLight);
  528.     RELEASE(lpmat);
  529.     RELEASE(lpbmat);
  530. }
  531.  
  532.  
  533. BOOL
  534. InitView(LPDIRECTDRAW lpDD, LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpDev, 
  535.            LPDIRECT3DVIEWPORT lpView, int NumTextures, 
  536.            LPD3DTEXTUREHANDLE TextureHandle)
  537. {
  538.     /* Variables for exectue buffer generation */
  539.     LPVOID lpBufStart, lpInsStart, lpPointer;
  540.     LPDIRECT3DEXECUTEBUFFER lpD3DExCmdBuf;
  541.     DWORD size;
  542.  
  543.     /* Background material variables */
  544.     D3DMATERIAL bmat;
  545.     D3DMATERIALHANDLE hbmat;
  546.     D3DMATERIAL mat;
  547.  
  548.     /*
  549.      * Set background to black material
  550.      */
  551.     if (lpD3D->lpVtbl->CreateMaterial(lpD3D, &lpbmat, NULL) != D3D_OK)
  552.         return FALSE;
  553.     memset(&bmat, 0, sizeof(D3DMATERIAL));
  554.     bmat.dwSize = sizeof(D3DMATERIAL);
  555.     bmat.dwRampSize = 1;
  556.     lpbmat->lpVtbl->SetMaterial(lpbmat, &bmat);
  557.     lpbmat->lpVtbl->GetHandle(lpbmat, lpDev, &hbmat);
  558.     lpView->lpVtbl->SetBackground(lpView, hbmat);
  559.     /*
  560.      * Set the view, projection and world matricies in an execute buffer
  561.      */
  562.     MAKE_MATRIX(lpDev, hView, view);
  563.     MAKE_MATRIX(lpDev, hProj, proj);
  564.     MAKE_MATRIX(lpDev, hWorld, world);
  565.     /*
  566.      * Create an execute buffer
  567.      */
  568.     size = 0;
  569.     size += sizeof(D3DINSTRUCTION) * 3;
  570.     size += sizeof(D3DSTATE) * 4;
  571.     memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
  572.     debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
  573.     debDesc.dwFlags = D3DDEB_BUFSIZE;
  574.     debDesc.dwBufferSize = size;
  575.     if (lpDev->lpVtbl->CreateExecuteBuffer(lpDev, &debDesc, &lpD3DExCmdBuf,
  576.                                            NULL) != D3D_OK)
  577.                                                return FALSE;
  578.     if (lpD3DExCmdBuf->lpVtbl->Lock(lpD3DExCmdBuf, &debDesc) != D3D_OK)
  579.         return FALSE;
  580.     lpBufStart = debDesc.lpData;
  581.     memset(lpBufStart, 0, size);
  582.     lpPointer = lpBufStart;
  583.     /*
  584.      * Fill the execute buffer with instructions
  585.      */
  586.     lpInsStart = lpPointer;
  587.     OP_STATE_TRANSFORM(3, lpPointer);
  588.         STATE_DATA(D3DTRANSFORMSTATE_WORLD, hWorld, lpPointer);
  589.         STATE_DATA(D3DTRANSFORMSTATE_VIEW, hView, lpPointer);
  590.         STATE_DATA(D3DTRANSFORMSTATE_PROJECTION, hProj, lpPointer);
  591.     OP_STATE_LIGHT(1, lpPointer);
  592.         STATE_DATA(D3DLIGHTSTATE_AMBIENT, RGBA_MAKE(40, 40, 40, 40), lpPointer);
  593.     OP_EXIT(lpPointer);
  594.     /*
  595.      * Setup the execute data describing the buffer
  596.      */
  597.     lpD3DExCmdBuf->lpVtbl->Unlock(lpD3DExCmdBuf);
  598.     memset(&d3dExData, 0, sizeof(D3DEXECUTEDATA));
  599.     d3dExData.dwSize = sizeof(D3DEXECUTEDATA);
  600.     d3dExData.dwInstructionOffset = (ULONG) 0;
  601.     d3dExData.dwInstructionLength = (ULONG) ((char *)lpPointer - (char*)lpInsStart);
  602.     lpD3DExCmdBuf->lpVtbl->SetExecuteData(lpD3DExCmdBuf, &d3dExData);
  603.     lpDev->lpVtbl->BeginScene(lpDev);
  604.     lpDev->lpVtbl->Execute(lpDev, lpD3DExCmdBuf, lpView, D3DEXECUTE_UNCLIPPED);
  605.     lpDev->lpVtbl->EndScene(lpDev);
  606.     /*
  607.      * We are done with the command buffer.
  608.      */
  609.     lpD3DExCmdBuf->lpVtbl->Release(lpD3DExCmdBuf);
  610.     /*
  611.      * Setup materials and lights
  612.      */
  613.     tube.hTex = TextureHandle[1];
  614.     if (lpD3D->lpVtbl->CreateMaterial(lpD3D, &lpmat, NULL) != D3D_OK)
  615.         return FALSE;
  616.     memset(&mat, 0, sizeof(D3DMATERIAL));
  617.     mat.dwSize = sizeof(D3DMATERIAL);
  618.     mat.diffuse.r = (D3DVALUE)1.0;
  619.     mat.diffuse.g = (D3DVALUE)1.0;
  620.     mat.diffuse.b = (D3DVALUE)1.0;
  621.     mat.diffuse.a = (D3DVALUE)1.0;
  622.     mat.ambient.r = (D3DVALUE)1.0;
  623.     mat.ambient.g = (D3DVALUE)1.0;
  624.     mat.ambient.b = (D3DVALUE)1.0;
  625.     mat.specular.r = (D3DVALUE)1.0;
  626.     mat.specular.g = (D3DVALUE)1.0;
  627.     mat.specular.b = (D3DVALUE)1.0;
  628.     mat.power = (float)20.0;
  629.     mat.dwRampSize = 16;
  630.     mat.hTexture = tube.hTex;
  631.     lpmat->lpVtbl->SetMaterial(lpmat, &mat);
  632.     lpmat->lpVtbl->GetHandle(lpmat, lpDev, &tube.hMat);
  633.     memset(&tube.light, 0, sizeof(D3DLIGHT));
  634.     tube.light.dwSize = sizeof(D3DLIGHT);
  635.     tube.light.dltType = D3DLIGHT_POINT;
  636.     tube.light.dvPosition.x = tube.cameraP.x;
  637.     tube.light.dvPosition.y = tube.cameraP.y;
  638.     tube.light.dvPosition.z = tube.cameraP.z;
  639.     tube.light.dcvColor.r = D3DVAL(0.9);
  640.     tube.light.dcvColor.g = D3DVAL(0.9);
  641.     tube.light.dcvColor.b = D3DVAL(0.9);
  642.     tube.light.dvAttenuation0 = (float)0.0;
  643.     tube.light.dvAttenuation1 = (float)0.0;
  644.     tube.light.dvAttenuation2 = (float)0.05;
  645.     if (lpD3D->lpVtbl->CreateLight(lpD3D, &tube.lpD3DLight, NULL)!=D3D_OK)
  646.         return FALSE;
  647.     if (tube.lpD3DLight->lpVtbl->SetLight(tube.lpD3DLight, &tube.light)
  648.         !=D3D_OK)
  649.         return FALSE;
  650.     if (lpView->lpVtbl->AddLight(lpView, tube.lpD3DLight) != D3D_OK)
  651.         return FALSE;
  652.  
  653.     /*
  654.      * Create an execute buffer
  655.      */
  656.     size = sizeof(D3DVERTEX) * NUM_V;
  657.     size += sizeof(D3DPROCESSVERTICES);
  658.     size += sizeof(D3DINSTRUCTION) * 6;
  659.     size += sizeof(D3DSTATE) * 4;
  660.     size += sizeof(D3DTRIANGLE) * NUM_TRI;
  661.     memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
  662.     debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
  663.     debDesc.dwFlags = D3DDEB_BUFSIZE;
  664.     debDesc.dwBufferSize = size;
  665.     if (lpDev->lpVtbl->CreateExecuteBuffer(lpDev, &debDesc, &lpD3DExBuf,
  666.                                            NULL) != D3D_OK)
  667.         return FALSE;
  668.     /*
  669.      * lock it so it can be filled
  670.      */
  671.     if (lpD3DExBuf->lpVtbl->Lock(lpD3DExBuf, &debDesc) != D3D_OK)
  672.         return FALSE;
  673.     lpBufStart = debDesc.lpData;
  674.     memset(lpBufStart, 0, size);
  675.     lpPointer = lpBufStart;
  676.     VERTEX_DATA(tube.lpV, NUM_V, lpPointer);
  677.     /*
  678.      * Save the location of the first instruction and add instructions to
  679.      * execute buffer.
  680.      */
  681.     lpInsStart = lpPointer;
  682.     OP_STATE_LIGHT(1, lpPointer);
  683.         STATE_DATA(D3DLIGHTSTATE_MATERIAL, tube.hMat, lpPointer);
  684.     OP_PROCESS_VERTICES(1, lpPointer);
  685.         PROCESSVERTICES_DATA(D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, NUM_V, lpPointer);
  686.     OP_STATE_RENDER(3, lpPointer);
  687.         STATE_DATA(D3DRENDERSTATE_TEXTUREHANDLE, tube.hTex, lpPointer);
  688.         STATE_DATA(D3DRENDERSTATE_WRAPU, TRUE, lpPointer);
  689.         STATE_DATA(D3DRENDERSTATE_WRAPV, TRUE, lpPointer);
  690.     /*
  691.      * Make sure that the triangle data (not OP) will be QWORD aligned
  692.      */
  693.     if (QWORD_ALIGNED(lpPointer)) {
  694.         OP_NOP(lpPointer);
  695.     }
  696.     OP_TRIANGLE_LIST(NUM_TRI, lpPointer);
  697.         tube.TriOffset = (char *)lpPointer - (char *)lpBufStart;
  698.         TRIANGLE_LIST_DATA(tube.lpTri, NUM_TRI, lpPointer);
  699.     OP_EXIT(lpPointer);
  700.     /*
  701.      * Setup the execute data describing the buffer
  702.      */
  703.     lpD3DExBuf->lpVtbl->Unlock(lpD3DExBuf);
  704.     memset(&d3dExData, 0, sizeof(D3DEXECUTEDATA));
  705.     d3dExData.dwSize = sizeof(D3DEXECUTEDATA);
  706.     d3dExData.dwVertexCount = NUM_V;
  707.     d3dExData.dwInstructionOffset = (ULONG) ((char *)lpInsStart - (char *)lpBufStart);
  708.     d3dExData.dwInstructionLength = (ULONG) ((char *)lpPointer - (char *)lpInsStart);
  709.     lpD3DExBuf->lpVtbl->SetExecuteData(lpD3DExBuf, &d3dExData);
  710.  
  711.     return TRUE;
  712. }
  713.